package com.sunbim.rsrv.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sunbim.rsrv.common.exception.RequestException;
import com.sunbim.rsrv.mapper.RelicsMapper;
import com.sunbim.rsrv.mapper.RiskBodyMapper;
import com.sunbim.rsrv.pojo.RiskBody;
import com.sunbim.rsrv.service.RiskBodyService;
import com.sunbim.rsrv.util.common.ProjectUtil;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 本体劣化风险 服务实现类
 * </p>
 *
 * @author yuhui
 * @since 2021-12-30
 */
@Service
public class RiskBodyServiceImpl extends ServiceImpl<RiskBodyMapper, RiskBody> implements RiskBodyService {

    @Autowired
    RiskBodyMapper riskBodyMapper;

    @Autowired
    RelicsMapper relicsMapper;

    @Override
    public RiskBody selectByRelicsId(Integer userId, Integer relicsId) {
        QueryWrapper<RiskBody> wrapper = new QueryWrapper<>();
        wrapper.eq("relics_id", relicsId);
        RiskBody riskBody = riskBodyMapper.selectOne(wrapper);
        if (ObjectUtil.isNull(riskBody)) throw new RequestException("文物id: " + relicsId + " 的body风险数据不存在");
        if (riskBody.getBody() != null)
            riskBody.getBody().setLevel(getLevel(userId, relicsId, riskBody.getBody().getScore(), "body"));
        if (riskBody.getCategory() != null)
            riskBody.getCategory().setLevel(getLevel(userId, relicsId, riskBody.getCategory().getScore(), "category"));

        return riskBody;
    }

    private int getLevel(Integer userId, Integer relicsId, Integer score, String column) {
        /* 计算风险等级 */
        int level;
        if (score == null || score == 0) level = 1;
        else {
            List<Integer> scoreList = riskBodyMapper.getScoreList(userId, column);
            // 去除重复值并排序
            List<Integer> sorted = scoreList.stream().collect(Collectors.toSet()).stream().sorted().collect(Collectors.toList());
            level = getLevel(score, sorted);

            // 获取该文物在对应用户下的总分排名
//            Integer rank = riskBodyMapper.getRank(userId, relicsId, column);
//            // 根据文物的所属用户id 获取所有风险数据
//            List<RiskBody> list = getAllByUserId(userId);
//            // 如果总数小于等于4, 获取前4名,去掉总分为0的数据, 排序取得风险等级
//            if (list.size() <= 4) {
//                // 统计总分不为0的风险数据
//                int count = 0;
//                for (RiskBody body : list) {
//                    if ("body".equals(column)) {
//                        if (0 != body.getBody().getScore()) ++count;
//                    } else if ("category".equals(column)) {
//                        if (0 != body.getCategory().getScore()) ++count;
//                    }
//                }
//                // 若总分均不为0
//                if (count == list.size()) level = count - rank + 1;
//                    // 若存在总分为0
//                else level = count - rank + 2;
//            }
//            // 否则根据排名和总数计算前百分位, 得到风险等级
//            else level = ProjectUtil.countLevel(rank, list.size());
        }
        return level;
    }

    @Override
    public void updateByRiskId(RiskBody params) {
        boolean isIdExist = riskBodyMapper.idExist(params.getId());
        if (!isIdExist) throw new RequestException("风险id: " + params.getId() + " 不存在");

        RiskBody.Body body = params.getBody();
        List<Map<String, Object>> bodyRisk = body.getRisk();
        if (CollectionUtils.isNotEmpty(bodyRisk)) {
            Integer score = bodyRisk.stream().mapToInt(stringObjectMap -> stringObjectMap.get("grade") != null ? (int) stringObjectMap.get("grade") : 0).sum();
            body.setScore(score);
        }
        RiskBody.Category category = params.getCategory();
        List<Map<String, Object>> categoryRisk = category.getRisk();
        if (CollectionUtils.isNotEmpty(categoryRisk)) {
            Integer score = categoryRisk.stream().mapToInt(stringObjectMap -> stringObjectMap.get("grade") != null ? (int) stringObjectMap.get("grade") : 0).sum();
            category.setScore(score);
        }
        params.setTotalScore(body.getScore() + category.getScore());
        riskBodyMapper.updateById(params);
    }

    public List<RiskBody> getAllByUserId(Integer userId) {
        QueryWrapper<RiskBody> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id", userId);
        return riskBodyMapper.selectList(wrapper);
    }

    /**
     * 计算风险等级
     *
     * @param score  当前文物“本体劣化风险”得分，或者“结构安全风险”得分
     * @param scores 当前用户下所有文物的“本体劣化风险”得分，或者“结构安全风险”得分集合，已按照从低到高排序，已去除未参评的文物
     * @return
     */
    public static int getLevel(Integer score, List<Integer> scores) {
        int level = 1;

        if (scores.size() <= 4) {
            level = scores.size() - scores.indexOf(score);
        }
        // 否则根据排名和总数计算前百分位, 得到风险等级
        else level = ProjectUtil.countLevel(scores.indexOf(score) + 1, scores.size());
        return level;

    }
}
